﻿using ECO.EventBus.Infrastructure;
using Newtonsoft.Json;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading.Channels;

namespace ECO.EventBus.Core
{
    public class EventBus
    {
        private readonly EventBusOptions _options;
        private readonly ConcurrentDictionary<Type, Channel<IEvent>> _eventChannels = new();
        private readonly ConcurrentDictionary<Type, List<Func<IEvent, Task>>> _eventHandlers = new();
        private readonly CancellationTokenSource _cts = new();

        public EventBus(EventBusOptions options)
        {
            _options = options;
        }

        // 发布事件
        public void Publish<TEvent>(TEvent @event) where TEvent : IEvent
        {
            @event.EventId = Guid.NewGuid();
            @event.CreatedAt = DateTime.UtcNow;

            if (_options.UsePool)
            {
                GetOrCreateChannel<TEvent>().Writer.TryWrite(@event);
            }
            else
            {
                ProcessEvent(@event);
            }
        }

        // 异步发布事件
        public async Task PublishAsync<TEvent>(TEvent @event) where TEvent : IEvent
        {
            @event.EventId = Guid.NewGuid();
            @event.CreatedAt = DateTime.UtcNow;

            if (_options.UsePool)
            {
                await GetOrCreateChannel<TEvent>().Writer.WriteAsync(@event);
            }
            else
            {
                await ProcessEventAsync(@event);
            }
        }

        // 订阅事件处理器
        public void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
        {
            var eventType = typeof(TEvent);
            var handlerType = handler.GetType();
            if (!_eventHandlers.ContainsKey(eventType))
            {
                _eventHandlers[eventType] = new List<Func<IEvent, Task>>();
            }

            _eventHandlers[eventType].Add(async @event =>
            {
                try
                {
                    await handler.HandleAsync((TEvent)@event);
                }
                catch (Exception ex)
                {
                    handler.HandleException((TEvent)@event, ex);
                }
            });

            if (_options.UsePool)
            {
                StartProcessingEvents(eventType);
            }
        }

        // 从程序集中自动注册事件处理器
        public void RegisterHandlersFromAssembly(Assembly assembly)
        {
            var handlerTypes = assembly.GetTypes()
                .Where(t => t.GetCustomAttributes<EventHandlerAttribute>().Any() &&
                           t.GetInterfaces().Any(i => i.IsGenericType &&
                                                  i.GetGenericTypeDefinition() == typeof(IEventHandler<>)));

            foreach (var handlerType in handlerTypes)
            {
                var attributes = handlerType.GetCustomAttributes<EventHandlerAttribute>();
                var handlerInstance = Activator.CreateInstance(handlerType);

                foreach (var attribute in attributes)
                {
                    var eventType = attribute.EventType;
                    var handlerInterface = typeof(IEventHandler<>).MakeGenericType(eventType);

                    if (handlerInterface.IsAssignableFrom(handlerType))
                    {
                        var subscribeMethod = typeof(EventBus).GetMethod("Subscribe")
                            ?.MakeGenericMethod(eventType);

                        subscribeMethod?.Invoke(this, new[] { handlerInstance });
                    }
                }
            }
        }

        // 从类型列表中注册事件处理器
        public void RegisterHandlersFromTypes(params Type[] handlerTypes)
        {
            foreach (var handlerType in handlerTypes)
            {
                var attributes = handlerType.GetCustomAttributes<EventHandlerAttribute>();
                var handlerInstance = Activator.CreateInstance(handlerType);

                foreach (var attribute in attributes)
                {
                    var eventType = attribute.EventType;
                    var handlerInterface = typeof(IEventHandler<>).MakeGenericType(eventType);

                    if (handlerInterface.IsAssignableFrom(handlerType))
                    {
                        var subscribeMethod = typeof(EventBus).GetMethod("Subscribe")
                            ?.MakeGenericMethod(eventType);

                        subscribeMethod?.Invoke(this, new[] { handlerInstance });
                    }
                }
            }
        }

        // 获取或创建事件通道
        private Channel<IEvent> GetOrCreateChannel<TEvent>() where TEvent : IEvent
        {
            var eventType = typeof(TEvent);
            return _eventChannels.GetOrAdd(eventType, _ => Channel.CreateUnbounded<IEvent>());
        }

        // 启动事件处理
        private void StartProcessingEvents(Type eventType)
        {
            // 已经在处理该事件类型
            if (_eventProcessors.ContainsKey(eventType)) return;
               
            // 确保通道存在
            if (!_eventChannels.TryGetValue(eventType, out var channel))
            {
                channel = Channel.CreateUnbounded<IEvent>();
                _eventChannels[eventType] = channel;
            }
            _eventProcessors[eventType] = Task.Run(async () =>
            {
                try
                {
                    while (!_cts.IsCancellationRequested)
                    {
                        var @event = await channel.Reader.ReadAsync(_cts.Token);
                        _ = ProcessEventAsync(@event);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error processing events of type {eventType.Name}: {ex.Message}");
                }
            }, _cts.Token);
        }

        // 处理单个事件
        private async Task ProcessEventAsync(IEvent @event)
        {
            var eventType = @event.GetType();
            if (_eventHandlers.TryGetValue(eventType, out var handlers))
            {
                var tasks = handlers.Select(handler => handler(@event)).ToList();
                await Task.WhenAll(tasks);
            }
        }

        private void ProcessEvent(IEvent @event)
        {
            var eventType = @event.GetType();
            if (_eventHandlers.TryGetValue(eventType, out var handlers))
            {
                foreach (var handler in handlers)
                {
                    handler(@event).Wait();
                }
            }
        }

        // 事件处理器任务
        private readonly ConcurrentDictionary<Type, Task> _eventProcessors = new();

        // 清理资源
        public void Dispose()
        {
            _cts.Cancel();
            _cts.Dispose();

            foreach (var channel in _eventChannels.Values)
            {
                channel.Writer.Complete();
            }
        }

    }
}
